package com.hlg.xboot.service;

import com.hlg.xboot.model.BaseDic;
import com.hlg.xboot.model.BaseDicTree;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import javax.persistence.EntityManager;
import javax.persistence.EntityManagerFactory;
import javax.persistence.Query;
import java.util.ArrayList;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

/**
 * Created by tianzw on 2017/5/3.
 */
@Service
public class DicsService {

    @Autowired
    private EntityManagerFactory entityManagerFactory;


    public List<BaseDic> queryBaseDicByName(String dicName) {
        List<Object[]> list = queryDicByName(dicName);
        return list.stream().map(objs ->{
            BaseDic dic = new BaseDic();
            dic.setCode((String)objs[0]);
            dic.setName((String)objs[1]);
            return dic;
        }).collect(Collectors.toList());
    }

    public List<BaseDicTree> queryBaseDicTreeByName(String dicName) {
        List<Object[]> list = queryDicTreeByName(dicName);
        return list.stream().map(objs ->{
            BaseDicTree dic = new BaseDicTree();
            dic.setCode((String)objs[0]);
            dic.setName((String)objs[1]);
            dic.setParentCode((String)objs[2]);
            return dic;
        }).collect(Collectors.toList());
    }

    public List<Object[]> queryDicByName(String dicName) {
        String sql = "select code, name from t_base_"+dicName+" order by code asc";
        return queryDicByNativeSQL(sql);
    }

    public List<Object[]> queryDicTreeByName(String dicName) {
        String sql = "select code, name, parent_code from t_base_"+dicName+" order by code asc";
        return queryDicByNativeSQL(sql);
    }

    public List<Object[]> queryDicByNameAndCols(String dicName, String cols) {
        String sql = "select " + cols + " from t_base_"+dicName+" order by code asc";
        return queryDicByNativeSQL(sql);
    }

    private List<Object[]> queryDicByNativeSQL(String sql) {
        EntityManager em =  entityManagerFactory.createEntityManager();
        Query query = em.createNativeQuery(sql);
        List list = query.getResultList();
        em.close();
        return (List<Object[]>)list;
    }

    /**
     * 构造树结构，暂时支持4级
     * @param list
     * @param <T>
     * @return
     */
    public <T extends BaseDicTree> List<Map<String, Object>> transTreeData(List<T> list) {
        if(list == null){
            return new ArrayList<>();
        }
        Map<String, T> treeMap = new LinkedHashMap<>();
        Map<String, T> secondMap = new LinkedHashMap<>();
        Map<String, T> thirdMap = new LinkedHashMap<>();
        list.forEach((item) ->{
            if(StringUtils.isEmpty(item.getParentCode())){
                treeMap.put(item.getCode(), item);
                secondMap.put(item.getCode(), item);
            }else if(treeMap.containsKey(item.getParentCode())){ //父节点是一级
                treeMap.get(item.getParentCode()).getChildren().add(item);
                secondMap.put(item.getCode(), item);
            }else if(secondMap.containsKey(item.getParentCode())){ //父节点是二级
                T parent = secondMap.get(item.getParentCode());
                treeMap.get(parent.getParentCode()).getChildren().forEach((parentNode) -> {
                    if(parentNode.getCode().equals(parent.getCode())) {
                        parentNode.getChildren().add(item);
                        thirdMap.put(item.getCode(), item);
                    }
                });
            }else if(thirdMap.containsKey(item.getParentCode())){ //父节点是三级
                final T grandParent = secondMap.get(thirdMap.get(item.getParentCode()).getParentCode());
                treeMap.get(grandParent.getParentCode()).getChildren().forEach((grandParentNode) -> {
                    if(grandParentNode.getCode().equals(grandParent.getCode())) { // 找到TreeMap里的祖父
                        grandParentNode.getChildren().forEach((parentNode) -> {
                            if(parentNode.getCode().equals(item.getParentCode())) { // 找到TreeMap里的父亲
                                parentNode.getChildren().add(item);
                            }
                        });
                    }
                });
            }
        });
        return treeMap.entrySet().stream().map((item) -> item.getValue().transformTreeModel()).collect(Collectors.toList());
    }

    public String getDicNameByCode(List<Map<String, Object>> dicList, String code){
        String name = "";
        for(Map<String, Object> item:dicList){
            if(item.get("code").equals(code)){
                name = (String)item.get("name");
                break;
            }
        }
        return name;
    }

}
